﻿using System;
using System.Collections.Generic;
using AutoMerge.Properties;

namespace AutoMerge
{
    /// <summary>
    /// Базовый класс для маркеров модификации
    /// </summary>
    public abstract class ModificationMarker: IComparable<ModificationMarker>
    {
        private static int _currentOrderIndex = int.MinValue;

        protected ModificationMarker(int sourceRowNum, string fileName, string subjectString, int versionRowNum)
        {
            SourceRowNum = sourceRowNum;
            FileName = fileName;
            SubjectString = subjectString;
            VersionRowNum = versionRowNum;
            OrderIndex = _currentOrderIndex++;
            ResultRowNum = -1;
        }
        /// <summary>
        /// Номер строки в исходном файле
        /// </summary>
        public int SourceRowNum { get; private set; }

        /// <summary>
        /// Номер строки в результирующем файле
        /// </summary>
        public int ResultRowNum { get; set; }

        /// <summary>
        /// Номер строки в файле с изменениями
        /// </summary>
        public int VersionRowNum { get; set; }

        /// <summary>
        /// Имя файла с изменениями
        /// </summary>
        public string FileName { get; private set; }

        /// <summary>
        /// Порядковый номер изменения
        /// </summary>
        public int OrderIndex { get; set; }

        /// <summary>
        /// Флаг конфликта
        /// </summary>
        public bool Conflict { get; set; }

        /// <summary>
        /// Значение строки (новой, измененной или удаленной)
        /// </summary>
        public string SubjectString { get; private set; }

        public int CompareTo(ModificationMarker other)
        {
            var result = SourceRowNum.CompareTo(other.SourceRowNum);
            if(result == 0)
                result = OrderIndex.CompareTo(other.OrderIndex);
            return result;
        }

        /// <summary>
        /// Получить имя операции
        /// </summary>
        /// <returns></returns>
        protected abstract string getOperationName();

        public override string ToString()
        {
            return string.Format(Resources.strLineNo, SourceRowNum+1) + 
                string.Format(getOperationName() + Resources.strLineInFile, SubjectString, FileName);
        }
    }

    /// <summary>
    /// Маркер создания строк
    /// </summary>
    public abstract class AddMarker : ModificationMarker
    {
        protected AddMarker(int sourceRowNum, string fileName, string newLine, int versionRowNum) 
            : base(sourceRowNum, fileName, newLine, versionRowNum)
        {
        }
    }

    /// <summary>
    /// Маркер вставки строк
    /// </summary>
    public class InsertMarker : AddMarker
    {
        public InsertMarker(int sourceRowNum, string fileName, string newLine, int versionRowNum)
            : base(sourceRowNum, fileName, newLine, versionRowNum)
        {
        }

        protected override string getOperationName() { return Resources.strInserted; }
    }

    /// <summary>
    /// Маркер добавления строк
    /// </summary>
    public class AppendMarker : AddMarker
    {
        public AppendMarker(int sourceRowNum, string fileName, string newLine, int versionRowNum)
            : base(sourceRowNum, fileName, newLine, versionRowNum)
        {
        }

        protected override string getOperationName() { return Resources.strAppended; }
    }

    /// <summary>
    /// Маркер удаления строки
    /// </summary>
    public class DeleteMarker : ModificationMarker
    {
        public DeleteMarker(int sourceRowNum, string fileName, string newLine, int versionRowNum) 
            : base(sourceRowNum, fileName, newLine, versionRowNum)
        {
        }

        protected override string getOperationName() { return Resources.strDeleted; }
    }

    /// <summary>
    /// Маркер изменения строки
    /// </summary>
    public class ChangeMarker : ModificationMarker
    {
        public ChangeMarker(int sourceRowNum, string fileName, string newLine, int versionRowNum)
            : base(sourceRowNum, fileName, newLine, versionRowNum)
        {
        }

        protected override string getOperationName() { return Resources.strChanged; }
    }

    /// <summary>
    /// Класс для проверки уникальности маркера новой строки (используется при вызовах Distinct)
    /// </summary>
    internal class EqComparerAdd : IEqualityComparer<AddMarker>
    {
        public bool Equals(AddMarker x, AddMarker y)
        {
            return x.SourceRowNum == y.SourceRowNum && x.SubjectString.Trim() == y.SubjectString.Trim();
        }

        public int GetHashCode(AddMarker obj)
        {
            return obj.SubjectString.GetHashCode();
        }
    }
}
